home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / ziplib / ziplib.php < prev   
PHP Script  |  2004-08-26  |  9KB  |  212 lines

  1. <?php
  2. // **************************
  3. // *      Ziplib 0.3.1      *
  4. // *    Created by: Seven   *
  5. // **************************
  6. //
  7. // Simple set of functions to create a zipfile
  8. // according to the PKWare specifications, which
  9. // can be found on:
  10. // http://www.pkware.com/products/enterprise/white_papers/
  11. // ⌐1989-2003, PKWARE Inc.
  12.  
  13. // functions in here start with zl, which comes from ZipLib ;)
  14.  
  15. // requires dostime.php
  16. $settings['offset'] = 1; // Holland ;)
  17.  
  18. require ('./convert.php');
  19.  
  20. class Ziplib {
  21.  
  22. var $archive;
  23. var $archive_fileinfo = array();
  24. var $archive_filecount;
  25. var $compr_lvl_last;
  26.  
  27. private function zl_compress($data,$level = "",$type = "") {
  28.     if($type != "g" && $type != "b" && $type != "n") {
  29.         // Darnit, they forgot to set the type. Assuming gZip if any compression
  30.         if($level >= 1 && $level <= 9) $type = "g";
  31.         elseif($level > 9) die("Compression level set too high");
  32.         else $type = "n";
  33.     }
  34.         
  35.     if($type == "g") {
  36.         $this->compr_lvl_last = 8;
  37.         RETURN gzdeflate($data,$level);
  38.     } elseif($type == "b") {
  39.         $this->compr_lvl_last = 12;
  40.         RETURN bzcompress($data,$level);
  41.     } else {
  42.         $this->compr_lvl_last = 0;
  43.         RETURN $data;
  44.     }
  45. }
  46.  
  47. public function zl_add_file($data,$filename,$comp = "") {
  48.     global $settings;
  49.     // if we already created a file, we'll make sure it'll be there in the coming zipfile ;)
  50.  
  51.     // first, checking some data
  52.     if(strlen($filename) > pow(2,16)-1) die("Filename $filename too long"); // ooh, dirty... dieing, will change later
  53.     if(strlen($data) > pow(2,32)-1) die("File $filename larger then 2GB, cannot continue"); // another one, naughty me ;)
  54.  
  55.     // $comp has a special format. the first character tells me about the compression, the second one represents the level
  56.     if(strlen($comp) == 1) {
  57.         // they still use the old method, assuming gzip
  58.         
  59.         $comp_type = "n";
  60.         $comp_lvl = 0;
  61.         if($comp >= 1 && $comp <= 9) {
  62.             $comp_type = "g";
  63.             $comp_lvl = $comp;
  64.         }
  65.     } else {
  66.         $comp_lvl = 5;
  67.         $comp_type = "n";
  68.         // hmmm, the new method. Is it valid?
  69.         if ($comp[0] == "b" OR $comp[0] == "g" OR $comp[0] == "n") $comp_type = $comp[0];
  70.         if (preg_match("/[0-9]/i",$comp[1])) $comp_lvl = $comp[1];
  71.     }
  72.  
  73.     // ok, let's get this bitch tidy:
  74.     // first adding a file
  75.     $compressed = $this->zl_compress($data,$comp_lvl,$comp_type);
  76.     $uncompressed = strlen($data);
  77.  
  78.     $newfile = "\x50\x4b\x03\x04";                // Header
  79.     $newfile .="\x00\x00";                    // Version needed to extract
  80.     $newfile .="\x00\x00";                    // general purpose bit flag
  81.     $newfile .=pack("v",$this->compr_lvl_last);        // compression method
  82.     $newfile .=pack("v",dostime_get($settings['offset']));            // last mod file time
  83.     $newfile .=pack("v",dosdate_get($settings['offset']));            // last mod file date
  84.     $newfile .=pack("V",crc32($data));            // CRC32
  85.     $newfile .=pack("V",strlen($compressed));        // compressed filesize
  86.     $newfile .=pack("V",$uncompressed);            // uncompressed filesize
  87.     $newfile .=pack("v",strlen($filename));            // length of filename
  88.     $newfile .="\x00\x00";                    // some sort of extra field ;)
  89.     $newfile .=$filename;
  90.     $newfile .=$compressed;
  91.  
  92.     $this->archive .= $newfile;
  93.  
  94.  
  95.     // some 'statistics' for this file ;)
  96.     $this->archive_filecount++;
  97.     $idf = $this->archive_filecount - 1;
  98.     $this->archive_fileinfo[$this->archive_filecount]['comp_type'] = $this->compr_lvl_last;
  99.     $this->archive_fileinfo[$this->archive_filecount]['size'] = strlen($data);
  100.     $this->archive_fileinfo[$this->archive_filecount]['size_comp'] = strlen($compressed);
  101.     $this->archive_fileinfo[$this->archive_filecount]['pkg_size'] = strlen($newfile);
  102.     if(!empty($this->archive_fileinfo[$idf]['local_stats_pointer'])) {
  103.         $this->archive_fileinfo[$this->archive_filecount]['local_stats_pointer'] = 
  104.         $this->archive_fileinfo[$idf]['local_stats_pointer'] +
  105.         $this->archive_fileinfo[$idf]['pkg_size'] + 1; // HACKERDIEHACK! only way to get local_stats_pointer to '0' (for now) in zl_pack
  106.     } else {
  107.         $this->archive_fileinfo[$this->archive_filecount]['local_stats_pointer'] = 1;
  108.     }
  109.     $this->archive_fileinfo[$this->archive_filecount]['name'] = $filename;
  110.     $this->archive_fileinfo[$this->archive_filecount]['crc32'] = crc32($data);
  111.     unset($file,$compressed); // to avoid having data in our memory double ;)
  112.     RETURN TRUE;
  113. }
  114.  
  115. public function zl_pack($comment) {
  116.     global $settings;
  117.     if(strlen($comment) > pow(2,16)-1) die("Comment too long"); // that's 3
  118.  
  119.     // now the central directory structure start
  120.     for($x=1;$x <= $this->archive_filecount;$x++) {
  121.         $file_stats = $this->archive_fileinfo[$x];
  122.         $cdss .= "\x50\x4b\x01\x02";            // Header
  123.         $cdss .="\x00\x00";                // version made by
  124.         $cdss .="\x00\x00";                // version needed to extract
  125.         $cdss .="\x00\x00";                // general purpose bit flag
  126.         $cdss .=pack("v",$file_stats['comp_type']);    // compression method
  127.         $cdss .=pack("v",dostime_get($settings['offset']));        // last mod file time
  128.         $cdss .=pack("v",dosdate_get($settings['offset']));        // last mod file date
  129.         $cdss .=pack("V",$file_stats['crc32']);        // CRC32
  130.         $cdss .=pack("V",$file_stats['size_comp']);    // compressed size
  131.         $cdss .=pack("V",$file_stats['size']);        // uncompressed size
  132.         $cdss .=pack("v",strlen($file_stats['name']));    // file name length
  133.         $cdss .="\x00\x00";                // extra field length
  134.         $cdss .="\x00\x00";                // file comment length
  135.         $cdss .="\x00\x00";                // disk number start
  136.         $cdss .="\x00\x00";                // internal file attributes
  137.         $cdss .="\x00\x00\x00\x00";            // external file attributes
  138.         $cdss .=pack("V",$file_stats['local_stats_pointer']-$x);    // relative offset of local header
  139.                                         // aka: The local_stats_pointer hack: part 2, see above
  140.         $cdss .=$file_stats['name'];
  141.     }
  142.  
  143.     // and final, the ending central directory structure! "WHOO HOOW!" (⌐Blur, 1998)
  144.     $cdse = "\x50\x4b\x05\x06";            // Header
  145.     $cdse .="\x00\x00";                // number of this disk
  146.     $cdse .="\x00\x00";                // number of the disk with the start of the central directory
  147.     $cdse .=pack("v",$this->archive_filecount);    // total number of entries in the central directory on this disk
  148.     $cdse .=pack("v",$this->archive_filecount);    // total number of entries in the central directory
  149.     $cdse .=pack("V",strlen($cdss));        // size of the central directory
  150.     $cdse .=pack("V",strlen($this->archive));    // offset of start of central directory with respect to the starting disk number
  151.     $cdse .=pack("v",strlen($comment));        // .ZIP file comment length
  152.     $cdse .=$comment;
  153.     
  154.     return $this->archive.$cdss.$cdse;
  155. }
  156.  
  157. public function zl_index_file($file) {
  158.     $fp = @fopen($file,"rb");
  159.     // ok, as we don't know what the exact position of everything is, we'll have to "guess" using the default sizes
  160.     //and set values in the zipfile. Basicly this means I have to go through the entire file, could take some time.
  161.     //Let's see if I can create an algorithm powerful enough.
  162.     if(!$fp) die("File empty");
  163.     $continue = 1;
  164.     $file_count = 0;
  165.  
  166.     while($continue) {
  167.         $content = fread($fp,30);
  168.         $id = substr($content,0,4);
  169.         if ($id == "\x50\x4b\x03\x04") {
  170.             // the method used is quite simple, load a file in the memory, and walk through several parts of it using substr
  171.             // As the PKZip format uses mostly fixed sizes for information, this isn't too hard to implement
  172.             // First I want everything tested, before I start giving this function a nice place in the class
  173.             $temp[$file_count]['file-size'] = ascii2dec(substr($content,18,4));
  174.             $temp[$file_count]['filename-size'] = ascii2dec(substr($content,26,2));
  175.             $temp[$file_count]['compression-type'] = ascii2dec(substr($content,8,2));
  176.             $temp[$file_count]['crc'] = ascii2dec(substr($content,14,4));
  177.             $temp[$file_count]['dostime'] = dostime_return(substr($content,10,2));
  178.             $temp[$file_count]['dosdate'] = dosdate_return(substr($content,12,2));
  179.  
  180.             $temp[$file_count]['filename'] = fread($fp,$temp[$file_count]['filename-size']);
  181.  
  182.             // As the Zip format does not include Content type headers, I'll create a nice little array with 
  183.             // extension/content type, and a small function to retreive it
  184.             $temp[$file_count]['file-type'] = ext2cth($temp[$file_count]['filename']);
  185.             $temp[$file_count]['content'] = fread($fp,$temp[$file_count]['file-size']);
  186.  
  187.             if ($temp[$file_count]['compression-type'] != 0 AND $temp[$file_count]['compression-type'] != 8 AND $temp[$file_count]['compression-type'] != 12) {
  188.                 $temp[$file_count]['lasterror'] = "Compression type not supported";
  189.             } else {
  190.                 if($temp[$file_count]['compression-type'] == 8) {
  191.                     $temp[$file_count]['content'] = gzinflate($temp[$file_count]['content']);
  192.                 } elseif ($temp[$file_count]['compression-type'] == 12) {
  193.                     $temp[$file_count]['content'] = bzdecompress($temp[$file_count]['content']);
  194.                 }
  195.                 $verify = crc32($temp[$file_count]['content']);
  196.                 if ($verify != $temp[$file_count]['crc']) {
  197.                     $temp[$file_count]['lasterror'] = "CRC did not match, possibly this zipfile is damaged";
  198.                 }
  199.             }
  200.             $file_count++;
  201.         } else {
  202.             $continue = 0;    
  203.         }
  204.  
  205.     }
  206.     fclose($fp);
  207.     unset($fp,$content,$file_count);
  208.     return $temp;
  209. }
  210. }
  211. ?>
  212.